﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml.Linq;
using COFE.Core;
using System.Net;
using System.IO;
using COFE.Web.NetClient;

namespace COFE.Web
{
    /// <summary>
    /// Load foreign enty data from an XmlElement. (Foreign)
    /// </summary>
    public class WSEntry : Entry
    {
        #region Constructor

        internal WSEntry(string host, XElement itemXml)            
        {
            _host = host;

            base.ID = new Guid(itemXml.Attribute(XNames.ID).Value);
            base.Path = itemXml.Element(XNames.Path).Value;
            if (itemXml.Element(XNames.Size) != null)
                base.Length = Int64.Parse(itemXml.Element(XNames.Size).Value);

            base.Name = COFEWSPath.GetFileName(base.Path);
            base.UtcTime = DateTime.Parse(itemXml.Element(XNames.Time).Value);
            base.BaseType = EntryTypeExtension.Parse(
                itemXml.Attribute(XNames.EntryBaseType).Value);
            foreach (var link in itemXml.Elements(XNames.Link))
            {
                MediaType mType =
                    MediaTypeExtension.Parse(link.Attribute(XNames.MediaType).Value);
                RelationType rType =
                    RelationTypeExtension.Parse(link.Attribute(XNames.RelationType).Value);
                _links.Add(
                    new Link(mType, rType, link.Attribute(XNames.Uri).Value)
                    );
            }
            
            loadProperties(itemXml);
        }



        #endregion

        #region Methods        

        public override IEnumerable<Link> GetLinks()
        {
            return _links;
        }

        public override Core.PropertyPair GetProperty(object property)
        {

            if (Metadata.Find(property) != null)
                return Metadata.Find(property);

            if (!_metadataLoaded)
                loadMetadata();

            if (Metadata.Find(property) != null)
                return Metadata.Find(property);

            throw new NotSupportedException(property.ToString());
        }

        public override Core.PropertyPair GetProperty(string propertyName)
        {
            return GetProperty(COFEShared.PropertyDictionary.GetProperty(propertyName));
        }

        public override System.IO.Stream OpenStream(bool write = false)
        {
            var downloadLink = _links.FirstOrDefault((link)
              => link.Relation == RelationType.Download);

            if (downloadLink == null || write)
                throw new NotSupportedException();

            return COFEWSShared.NetClient.Get(_host + downloadLink.Uri).GetResponseStream();            
        }

        public override void Refresh()
        {
            loadMetadata();
        }

        private void updateMetadataList()
        {
            _metadataList =
               _metadatas == null ?
               _properties :
               new MetadataList(_metadatas.Union(_properties).Distinct());
        }

        private void loadProperties(XElement elementXml)
        {
            _properties = MetadataList.FromXml(elementXml);
            updateMetadataList();          
        }

        private void loadMetadata()
        {
            var metadataLink = _links.FirstOrDefault((link)
                => link.Relation == RelationType.Metadata);
            if (metadataLink != null)
            {
                var response =
                    COFEWSShared.NetClient.Get(_host + metadataLink.Uri);
                XElement metadataXml = XElement.Load(
                    new StreamReader(response.GetResponseStream()));
                _metadatas = MetadataList.FromXml(metadataXml);
            }

            updateMetadataList();
            _metadataLoaded = true;
        }

        #endregion

        #region Data

        private string _host;
        private List<Link> _links = new List<Link>();
        private MetadataList _properties, _metadatas;        
        private bool _metadataLoaded = false;

        #endregion

        #region Public Properties

        public override Guid EntryTypeID
        {
            get
            {
                if (!_metadataLoaded)
                    loadMetadata();

                var ppair = base.Metadata.Find(FileSystemInfoProperties.EntryTypeInfoKey);
                return ppair != null ? (Guid)ppair.Value : Guid.Empty;
            }

            protected set
            {
            }
        }

        public override object[] MetadataProperties
        {
            get
            {
                if (!_metadataLoaded)
                    loadMetadata();
                return base.MetadataProperties;
            }
            protected set
            {

            }
        }

        #endregion
    }
}
